#========================================
# author: changlong.zang
#   mail: zclongpop@163.com
#   date: Sat, 24 Jan 2015 17:04:58
#=======================================
import sys, string, os, re
from PyQt4 import QtCore, QtGui, uic
from FoleyUtils import scriptTool
#--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
def loadUi(uiPath):
    '''
    read an ui file, get two classes to return..
    '''
    windowClass, baseClass = uic.loadUiType(uiPath)
    return windowClass, baseClass



def compileWindowsFileName(fullPath):
    '''
    build a not exists windows file name...
    Exp:  
        D:/text         -> D:/text(1)         -> D:/text(2)         -> D:/text(3) ... D:/text(n+1)
        E:/Document.txt -> E:/Document(1).txt -> E:/Document(2).txt -> E:/Document(3).txt ... E:/Document(n+1).txt
    '''
    if not os.path.isfile(fullPath) and not os.path.isdir(fullPath):
        return fullPath
    
    fname, fextension = os.path.splitext(fullPath)
    res = re.search('\(\d+\)$', fname)
    if res:
        index = string.zfill(int(res.group()[1:-1]) + 1, len(res.group()) - 2)
        fname  = re.sub('\(\d+\)$', '(%s)'%index, fname)
    else:
        fname      = '%s(1)'%fname
    fullName = fname + fextension
    
    return compileWindowsFileName(fullName)



def SerializationObjectNames(fileList, nameFormat='Temp@', start=0, padding=3):
    '''
    fileList must is a list or a tuple
    nameFormat mutst have one " * "
    '''
    if not isinstance(fileList, (list, tuple)):
        return
    
    if nameFormat.count('@') != 1:
        return
    
    newNameList = []
    for i, obj in enumerate(fileList):
        newName = compileWindowsFileName(nameFormat.replace('@', string.zfill(i + start, padding)) + os.path.splitext(obj)[-1])
        newNameList.append(newName)
    return newNameList



class ListModel(QtCore.QAbstractListModel):
    '''
    List model for files, display & edit..
    '''
    WARNING_ICON = None
    SUCESS_ICON  = None
    def __init__(self, fileList=[], parent=None):
        super(ListModel, self).__init__(parent)
        self.__baseList = fileList[:]
        self.__fileList = fileList[:]


    def rowCount(self, index=QtCore.QModelIndex()):
        return len(self.__fileList)


    def data(self, index, role):
        #- file names
        if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
            return self.__fileList[index.row()]
        
        #- text color
        if role == QtCore.Qt.ForegroundRole:
            if self.__fileList.count(self.__fileList[index.row()]) > 1:
                return QtGui.QColor(255, 0, 0)
            
            if self.__fileList[index.row()] != self.__baseList[index.row()]:
                return QtGui.QColor(79, 219, 69)
        
        #- text Tip
        if role == QtCore.Qt.ToolTipRole:
            return self.__baseList[index.row()]
        
        #- warning icon
        if role == QtCore.Qt.DecorationRole:
            if self.__fileList.count(self.__fileList[index.row()]) > 1:
                if not isinstance(self.WARNING_ICON, QtGui.QPixmap):
                    self.WARNING_ICON = QtGui.QPixmap(os.path.join(scriptTool.getScriptPath(), 'icons', 'warning.png'))
                return self.WARNING_ICON
            
            if self.__fileList[index.row()] != self.__baseList[index.row()]:
                if not isinstance(self.SUCESS_ICON, QtGui.QPixmap):
                    self.SUCESS_ICON = QtGui.QPixmap(os.path.join(scriptTool.getScriptPath(), 'icons', 'ok-green.png'))
                return self.SUCESS_ICON

    def flags(self, index):
        #- what you can do it
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
    
    
    def setData(self, index, value, role):
        #- user seted value
        if role == QtCore.Qt.EditRole:
            if isinstance(value, basestring):
                self.__fileList[index.row()] = '%s'%value
            else:
                self.__fileList[index.row()] = '%s'%value.toString()
        self.dataChanged.emit(index, index)
        return True


    def insertRow(self, row, value, index=QtCore.QModelIndex()):
        self.beginInsertRows(index, row, row)
        self.__fileList.insert(row, value)
        self.__baseList.insert(row, value)
        self.endInsertRows()

    
    
    def clear(self):
        '''
        clear model datas for empoty view...
        '''
        self.beginRemoveRows(QtCore.QModelIndex(), 0, self.rowCount())
        del self.__baseList[:]
        del self.__fileList[:]
        self.endRemoveRows()



    def getValue(self, row):
        return self.__baseList[row]
    


    def result(self):
        return self.__baseList, self.__fileList


#-------------------------------------------------------------------------------------

windowClass, baseClass = loadUi(os.path.join(scriptTool.getScriptPath(), 'nameToolUI.ui'))
class NameUI(windowClass, baseClass):
    '''
    user control pannel...
    '''
    def __init__(self, parent=None):
        super(NameUI, self).__init__(parent)
        self.setupUi(self)
        #----------------------------------------------------
        #- setModel
        self.__listModel = ListModel()
        self.listView.setModel(self.__listModel)
        #----------------------------------------------------
        self.show()
        #-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        self.__textIndex    = 0
        self.__textMaxIndex = 0
        self.on_actionUiVisibleSwitch_triggered(True)
        #-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


    def on_btn_setpath_clicked(self, args=None):
        if args == None:return
        dialog = QtGui.QFileDialog()
        dialog.setFileMode(QtGui.QFileDialog.Directory)
        dialog.exec_()
        
        if not dialog.result():
            return
        
        selectionList = dialog.selectedFiles()
        if not selectionList:
            return
        self.LET_path.setText(os.path.normpath('%s'%selectionList[0]))
        



    def on_LET_path_textChanged(self, dirPath):
        self.on_btn_refresh_clicked(True)



    def __setNameData(self):
        searchText = '%s'%self.LET_inputA.text()
        for i in range(self.__listModel.rowCount()):
            orignalText = self.__listModel.getValue(i)
            #- prefix
            if self.rdn_pre.isChecked():
                resultText = '%s%s%s'%(os.path.splitext(orignalText)[0][:self.__textIndex],  searchText, os.path.splitext(orignalText)[0][self.__textIndex:]) + os.path.splitext(orignalText)[1]
           
            #- defind format
            elif self.rdn_def.isChecked():
                if not re.search('@', searchText):
                    return
                resultText  = SerializationObjectNames(self.__listModel.result()[0], searchText, 1)[i]
           
            #- search replace
            else:
                replaceText = '%s'%self.LET_inputB.text()
                resultText  = orignalText.replace(searchText, replaceText)
            
            #- set Model data
            self.__listModel.setData(self.__listModel.index(i, 0), resultText, QtCore.Qt.EditRole)



    def on_actionUiVisibleSwitch_triggered(self, args=None):
        if args == None:return
        if self.rdn_pre.isChecked():
            self.widget_buttonBox.setVisible(True)
            self.lab_Ps.setVisible(False)
            self.LET_inputB.setVisible(False)
            self.widget_stringData.setVisible(False)

        elif self.rdn_def.isChecked():
            self.widget_buttonBox.setVisible(False)
            self.lab_Ps.setVisible(True)
            self.LET_inputB.setVisible(False)
            self.widget_stringData.setVisible(False)

        else:   
            self.widget_buttonBox.setVisible(False)
            self.lab_Ps.setVisible(False)
            self.LET_inputB.setVisible(True)
            self.widget_stringData.setVisible(True)


    def on_LET_inputA_textChanged(self, text):
        if re.search('["/\*\?:<>\\\]', text):
            return
        self.__setNameData()


    def on_LET_inputB_textChanged(self, text):
        if re.search('["/\*\?:<>\\\]', text):
            return        
        self.__setNameData()

    def on_cbx_searchData_currentIndexChanged(self, args):
        if isinstance(args, int):return
        self.LET_inputA.setText(args)
    
    def on_cbx_replaceData_currentIndexChanged(self, args):
        if isinstance(args, int):return
        self.LET_inputB.setText(args)
    
    #=======================================================================================================================================
    
    def on_btn_top_clicked(self, args=None):
        if args == None:return
        self.__textIndex = 0
        self.__setNameData()



    def on_btn_left_clicked(self, args=None):
        if args == None:return
        self.__textIndex = min(max(0, self.__textIndex - 1), self.__textMaxIndex)
        self.__setNameData()


        
    def on_btn_right_clicked(self, args=None):
        if args == None:return
        self.__textIndex = min(max(0, self.__textIndex + 1), self.__textMaxIndex)
        self.__setNameData()



    def on_btn_end_clicked(self, args=None):
        if args == None:return
        self.__textIndex = self.__textMaxIndex
        self.__setNameData()
    
    #=======================================================================================================================================      

    def on_btn_refresh_clicked(self, args=None):
        if args == None:return
        #- clear List
        self.__listModel.clear()

        dirPath = '%s'%self.LET_path.text()
        if not os.path.isdir(dirPath):return
        files = os.listdir(dirPath)
        
        #- add Files
        for i, f in enumerate(files):
            self.__listModel.insertRow(i, '%s'%f)
            self.__textMaxIndex = max(self.__textMaxIndex, len(os.path.splitext(f)[0]))



    def on_btn_rename_clicked(self, args=None):
        if args == None:return
        self._windowsRename()
        #- refresh List
        self.on_btn_refresh_clicked(True)

    
    #=======================================================================================================================================
    def _windowsRename(self):
        path = '%s'%self.LET_path.text()
        baseNameList, resultNameList = self.__listModel.result()
        for baseName, resultName in zip(baseNameList, resultNameList):
            if baseName == resultName:continue
            os.rename(os.path.join(path, baseName), compileWindowsFileName(os.path.join(path, resultName)))
    #=======================================================================================================================================
    
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    wnd = NameUI()
    wnd.show()
    app.exec_()